# thread_scheduler.py
import threading
import queue
import atexit

class ThreadScheduler:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._initialized = False
        return cls._instance
    
    def __init__(self):
        if self._initialized:
            return
            
        self.task_queue = queue.Queue()
        self.main_thread = threading.main_thread()
        self.executor_thread = None
        self.running = True
        self._initialized = True
        
        # 自动启动执行线程
        self.start()
        # 注册退出清理
        atexit.register(self.shutdown)
    
    def start(self):
        """启动任务执行线程"""
        if self.executor_thread and self.executor_thread.is_alive():
            return
            
        self.executor_thread = threading.Thread(
            target=self._main_thread_task_executor, 
            daemon=True
        )
        self.executor_thread.start()
    
    def shutdown(self):
        """停止调度器并清理资源"""
        self.running = False
        if self.executor_thread and self.executor_thread.is_alive():
            self.executor_thread.join(timeout=1.0)
    
    def _main_thread_task_executor(self):
        """后台执行线程的主循环"""
        # 导入PyQt相关模块
        from PyQt5.QtCore import QObject, QEvent, QCoreApplication, QMetaObject, Qt
        
        # 自定义事件类型，用于在主线程中执行任务
        class MainThreadTask(QEvent):
            EVENT_TYPE = QEvent.registerEventType()
            
            def __init__(self, func, args, kwargs, container, event):
                super().__init__(MainThreadTask.EVENT_TYPE)
                self.func = func
                self.args = args
                self.kwargs = kwargs
                self.container = container
                self.event = event
                
        # 自定义事件接收器
        class EventReceiver(QObject):
            def __init__(self):
                super().__init__()
                
            def event(self, event):
                if event.type() == MainThreadTask.EVENT_TYPE:
                    try:
                        result = event.func(*event.args, **event.kwargs)
                        event.container.append(result)
                    except Exception as e:
                        event.container.append(e)
                    finally:
                        event.event.set()
                    return True
                return super().event(event)
                
        # 创建事件接收器
        receiver = EventReceiver()
        
        while self.running and self.main_thread.is_alive():
            try:
                # 获取任务，设置短暂超时防止永久阻塞
                task = self.task_queue.get(timeout=0.1)
                func, args, kwargs, container, event = task
                
                try:
                    # 创建主线程任务事件
                    task_event = MainThreadTask(func, args, kwargs, container, event)
                    # 将事件发送到主线程
                    QCoreApplication.instance().postEvent(receiver, task_event)
                    # 等待事件处理完成
                    event.wait()
                except Exception as e:
                    container.append(e)
                    event.set()
                    
            except queue.Empty:
                # 队列为空时继续轮询
                continue
            except Exception as e:
                # 记录意外错误但保持运行
                import logging
                logging.error(f"Task executor error: {e}")
    
    def run_in_main_thread(self, func, *args, **kwargs):
        """
        在程序主线程运行函数
        :param func: 要执行的函数
        :param args: 函数位置参数
        :param kwargs: 函数关键字参数
        :return: 函数的执行结果
        """
        # 导入PyQt相关模块
        from PyQt5.QtCore import QCoreApplication
        
        # 如果当前已经是主线程，直接执行
        if threading.current_thread() is self.main_thread:
            return func(*args, **kwargs)
            
        # 如果没有QApplication实例，则无法使用事件系统
        if QCoreApplication.instance() is None:
            import logging
            logging.warning("No QApplication instance available, cannot run in main thread properly")
            return func(*args, **kwargs)
            
        # 准备任务执行容器和事件
        result_container = []
        done_event = threading.Event()
        
        # 将任务放入队列
        self.task_queue.put((func, args, kwargs, result_container, done_event))
        
        # 等待任务完成
        done_event.wait()
        
        # 处理结果或异常
        if result_container and isinstance(result_container[0], Exception):
            raise result_container[0]
        return result_container[0] if result_container else None

# 全局单例调度器
scheduler = ThreadScheduler()

# 公共接口
run_in_main_thread = scheduler.run_in_main_thread
start_scheduler = scheduler.start
shutdown_scheduler = scheduler.shutdown